<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/6/11
 * Time: 9:10
 */

namespace Fanpaiji\Fpj;


use Fanpaiji\Tools;

class Index
{
    protected $pai_num  = 5;  // 发牌数
    protected $p        = [
        1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10,11,12,13,
        14,15,16,17,18,19,20,21,22,23,24,25,26,
        27,28,29,30,31,32,33,34,35,36,37,38,39,
        40,41,42,43,44,45,46,47,48,49,50,51,52,100,200
    ];  // 原牌。

    protected $pai_shuffle; // 洗牌后的牌

    protected $pai_key; // 发牌完成后，牌的key 通过key获取牌的大小

    protected $pai_content = [1=>'A',2=>2,3=>3,4=>4,5=>5,6=>6,7=>7,8=>8,9=>9,10=>10,11=>'J',12=>'Q',13=>'K',100=>'Queen',200=>'KING'];  // 牌的内容

    protected $pai_huase   = [0=>'heitao', 1=>'hongtao', 2=>'meihua', 3=>'fangkuai', 4=>'wang']; //0黑桃，1红桃，2梅花，3方块，4大小王   牌的花色

    protected $pai_icon    = [0=>'♠', 1=>'♥', 2=>'♣', 3=>'♦', 4=> 'Ψ']; // 牌花色的图标

    protected $pai_arr; // 最后的牌

    protected $pai_status;  // 最后的牌满足的牌型

    protected $king_hua_val=4; // 定义王牌的花色值

    protected $king_num = 0; // 初始化 王牌的个数

    protected $pai_num_arr;
    protected $pai_num_as_arr;
    protected $pai_hua_num_arr;
    /**
    规则
    初始有5张牌给玩家，玩家可以选择保留自己想要的任意数量的牌，然后将不牌换掉。换完牌后的5张牌如果能组成牌型则按牌型赔率进行结算。
    不能满足牌型则底注被系统收走
    牌型及牌型倍数大小王可以当作任意牌
    最终牌型只记能组成的最大牌型
    牌型定义
    五条：四张同样的牌+王牌
    同花大顺：同花色的10、J、Q、K、A
    同花顺：同花色的顺子（不包括同花大顺）
    四条：四张一样的牌
    葫芦：三张一样的牌+一对
    同花：同花色的五张牌
    顺子：数字相连的五张牌
    三条：三张一样的牌
    两对：两个对子
    一对：对8以上的对子（包含对8）
    牌型的出现概率是基于赢牌之后的概率
    牌型      英文      高倍      中倍      低倍      出现概率
    五条      K.        500       400        300      1‰
    同花大顺  S.        250       200       150       2‰
    同花顺    F.        140       120       100        2‰
    四条      K.        60        50        40        5‰
    葫芦      H.        12        10        8         30‰
    同花      L.         8        7         6         30‰
    顺子      T.         6        5         4         80‰
    三条      K.          3       3         3         150‰
    两对      P.          2       2         2         200‰
    一对      P.          1       1         1         500‰
     *
    流程 - yx
    选择空闲机器进入 yx
    进入yx进行押注
    玩家自由选择押注多少，同时各牌型对应的收益将即时改变。
    此时，界面上的五张牌是背面朝上
    押底注阶段按钮“大”“比倍”“小”“得分”“清除”置灰，不可操作（有押注后“清除”变亮）
    开始游戏
    下好底注后点击“启动”开始游戏
    五张牌依次翻开，并伴随“翻牌”的音效
    如果此时已经有能满足牌型的牌，系统自动把满足牌型的牌转入保留状态
    换牌
    单击想要的牌，牌面显示“保留”字样，再次单击后取消
    选好要保留的牌后点击“启动”，系统会自动将没有被保留的牌换掉
    从左至右点击五张牌分别发出“翻牌”的音效
    结算
    系统自动检测最终的5张牌所能组成的最大牌型
    如果能满足牌型，则根据相对应的牌型以及倍率对玩家进行奖励
    如果不能满足牌型，则底注消失
    押大小
    当玩家满足牌型后，会有一个押大小的机会
    玩家可以自行选择押大小或者跳过这个阶段直接领取奖励
    玩家选择押的大小后开牌，押中则奖励×2，可以继续将所得奖励进行押大小，押错则奖励消失，最多能连续押中7次
    8、9、10、J、Q、K为大；1、2、3、4、5、6为小；7为中不计胜负重新开牌；大小王则百搭（必赢）
     */

    /**
     * 开始
     */
    public function start()
    {
        $pai_shuffle = $this->p;
        shuffle($pai_shuffle);  // 洗牌
//        $this->pai_shuffle = $pai_shuffle;
        $this->pai_shuffle  = $this->p;
        $this->pai_key      = array_rand( $pai_shuffle ,$this->pai_num ); // 发牌
        $this->paishu();
        $this->paiStatus();
    }

    /**
     * 获取牌数 = 读取
     */
    public function paishu()
    {
        $paiArr = [];
        $this->pai_key = [11,14,8,8,5];
        foreach ( $this->pai_key as $paikey ) {
            $paiArr[] = $this->jisuan( $this->pai_shuffle[$paikey] );
        }
        $this->pai_arr = $paiArr;
    }

    /**
     * 计算牌数  牌的花色，牌的大小
     * @param int $num  // 抽到的牌
     * @return array
     */
    public function jisuan( int $num )
    {
        if ( $num != 100 && $num != 200 ) {
            $hua_num = (int)( $num / 13 ); // 花色 0黑桃，1红桃，2梅花，3方块，5大小王
            $pai_num = $num % 13; // 牌数
            $hua_num = $pai_num ? $hua_num : ( $hua_num - 1 );
            $pai_num = $pai_num ? $pai_num : 13;
        } else {
            $hua_num = $this->king_hua_val;
            $pai_num = $num;
        }
        $hua_val = $this->pai_huase[$hua_num];
        $pai_val = $this->pai_content[$pai_num];
        $pai_ico = $this->pai_icon[$hua_num];
        $pai_num_as = 0;
        if ( $pai_num == 1 || $pai_num >= 10 ) {  // 只有牌值大于等于10的才会有pai_num_as的值
            $pai_num_as = ( $pai_num == 1 ) ? '14' : $pai_num;
            if ( $pai_num == 100 || $pai_num == 200 ) {  // 计算王牌的个数
                $this->king_num = $this->king_num + 1;
            }
        }
        return $arr = ['hua_num'=>$hua_num, 'pai_num'=>$pai_num, 'hua_val'=>$hua_val,'pai_val'=>$pai_val, 'pai_icon'=>$pai_ico, 'pai_num_as'=>$pai_num_as, 'yuan'=>$num];
    }

    public function paiStatus()
    {
        $this->pai_num_arr      = array_column( $this->pai_arr, 'pai_num' );
        $this->pai_num_as_arr   = array_column( $this->pai_arr, 'pai_num_as' );
        $this->pai_hua_num_arr  = array_column( $this->pai_arr, 'hua_num' );
        $this->huLu();
    }

    /**
     * 五条
     * 四张同样的牌+王牌
     * @return int
     */
    public function wuTiao()
    {
        $pai_num_arr = $this->pai_num_arr;
        sort($pai_num_arr);
        $pai_val = $pai_num_arr[0]; unset( $pai_num_arr[0] );
        $status  = 1;
        foreach ( $pai_num_arr as $pai_num ) {
            if ( $pai_val != $pai_num && $pai_num != 100 && $pai_num != 200 ) {
                $status = 0;break;
            }
        }
        $this->pai_status = $status ? "K5" : 0;
        return $status;

    }

    /**
     * 同花大顺
     * 同花色的10、J、Q、K、A
     * @return int
     */
    public function tongHuaDaShun()
    {
        if ( !$this->isTongHua() ) { // 不是同花
            return 0;
        }
        $pai_num_arr = $this->pai_num_as_arr;
        $status = 0;
        if ( !in_array( 0, $pai_num_arr ) ) { // 判断 pai_num_as 是否都有值
            sort($pai_num_arr);
            if ( $this->isShunZi( $pai_num_arr ) ) {  // 判断第一个数是否是
                $status = 1;
            }
        }
        $this->pai_status = $status ? 'S' : 0;
        return $status;
    }

    /**
     * 同花顺
     * 同花色的顺子（不包括同花大顺）
     * @return int
     */
    public function tongHuaShun()
    {
        if ( !$this->isTongHua() ) { // 不是同花
            return 0;
        }
        $pai_num_as_arr = $this->pai_num_as_arr;
        $status = 0;
        if ( in_array( 0, $pai_num_as_arr ) ) { // 判断 pai_num_as 是否都有值
            $pai_num_arr = $this->pai_num_arr;
            sort($pai_num_arr);
            if ( $this->isShunZi( $pai_num_arr ) ) {
                $status = 1;
            }
        }
        $this->pai_status = $status ? 'F' : 0;
        return $status;
    }

    /**
     * 四条
     * 四张一样的牌
     * @return int
     */
    public function siTiao()
    {
        $tiaozi = $this->isTiaoZi();
        $status = 1;
        if ( $tiaozi < 4 ) {
            $status = 0;
        }
        $this->pai_status = $status ? 'K4' : 0;
        return $status;
    }


    /**
     * 葫芦：三张一样的牌+一对
     * 可能出现的情况
     * 1、aaabb 2、aabbw
     */
    public function huLu()
    {
//        $pai_num_arr = $this->pai_num_arr;
//        $isRepeat = $this->isRepeat( $pai_num_arr );
//        if ( $isRepeat['status'] == 0 ) {
//            return 0;
//        }
//
//        Tools::showData( $isRepeat );
    }


    /**
     * 同花
     * 同花色的五张牌
     */
    public function tongHua()
    {
        $isTonghua = $this->isTongHua();
        $this->pai_status = $isTonghua ? 'L' : 0;
        return $isTonghua;
    }


    /**
     * 顺子：数字相连的五张牌
     * @return int
     */
    public function shunZi()
    {
        $pai_num_arr = $this->pai_num_as_arr;
        $isShunzi    = $this->isShunZi($pai_num_arr);
        if ( !$isShunzi ) {
            $pai_num_as_arr = $this->pai_num_as_arr;
            $isShunzi       = $this->isShunZi( $pai_num_as_arr );
        }
        $this->pai_status = $isShunzi ? 'T' : 0;
        return $isShunzi;
    }




    /**
     * 判断是否是 同花
     * @return int
     */
    public function isTongHua()
    {
        $pai_hua_arr = $this->pai_hua_num_arr;
        sort( $pai_hua_arr );
        $hua_val = $pai_hua_arr[0]; unset( $pai_hua_arr[0] );
        $status  = 1;
        foreach ( $pai_hua_arr as $hua_num ) {
            if ( $hua_val != $hua_num && $hua_num != $this->king_hua_val ) {
                $status = 0;break;
            }
        }
        return $status;
    }

    /**
     * 判断是否是 顺子
     * @param array $arr
     */
    public function isShunZi( Array $arr )
    {
        $isRepeat = $this->isRepeat( $arr );
        if ( $isRepeat['status'] == 1 ) { // 判断是否有重复的牌
            return 0;
        }
        $pai_val    = $arr[0]; unset( $arr[0] );
        $status     = 1;
        $king_num   = $this->king_num;
        foreach ( $arr as $pai_num ) {
            if ( $pai_num !=100 && $pai_num !== 200 ) {  // 判断是否是王牌  不是王牌
                $cha = $pai_num - $pai_val - 1;
                if ( $cha != 0 ) {
                    if ( $cha > $king_num ) {
                        $status =  0;break;
                    } else {
                        $king_num = $king_num - $cha;
                    }
                }
            } else {   //　是王牌
                $status = 1;break;
            }
            $pai_val = $pai_num;
        }
        return $status;
    }

    /**
     * 判断是否有 重复的牌 相同的牌
     */
    public function isRepeat( array $arr )
    {
        $bb = array_count_values( $arr );
        $status = 0;
        if ( max( $bb ) > 1 ) {
            $status = 1;
        }
        return ['status'=> $status, 'data'=>$bb];
    }

    /**
     * 判断是否是条子，几条相同的
     * @return int
     */
    public function isTiaoZi()
    {
        $pai_num_arr = $this->pai_num_arr;
        sort($pai_num_arr);
        $tiaozi = 1;
        for ( $i=0; $i < count( $pai_num_arr ); $i++ ) {
            $tz = 1;
            for ( $j=($i+1); $j < count( $pai_num_arr ); $j++ ) {
                if ( $pai_num_arr[$i] == $pai_num_arr[$j] || $pai_num_arr[$j] == 100 || $pai_num_arr[$j] == 200 ) {
                    $tz++;
                }
            }

            if ( $tz > $tiaozi ) {
                $tiaozi = $tz;
            }
        }
        return $tiaozi;
    }
}